/*
 * ExtentCalculator.java
 *
 * Created on 2003/03/26, 12:08
 */

package name.marz.to.go.btree.ui.swing;

import java.awt.Dimension;
import java.util.HashMap;
import java.util.Map;

import name.marz.to.go.btree.node.AbstractNode;
import name.marz.to.go.btree.node.Node;
import name.marz.to.go.btree.node.NodeVisitor;


/**
 *
 * @author  masaru-gotou
 */
public class ExtentCalculator implements NodeVisitor {
	private Map<Node, NodeExtent> extents = new HashMap<Node, NodeExtent>();
	private GraphicsConfigration gc;
	
	/** Creates a new instance of Class */
	public ExtentCalculator(GraphicsConfigration config) {
		gc = config;
	}
	
	public Map<Node,NodeExtent> getExtents() {
		return extents;
	}
	
	/** Nodeに訪問する
	 * @param n 訪問するNode
	 */
	@Override
	public void visit(Node node) {
		NodeExtent child_extent = new NodeExtent();
		Object leftpointer = node.getLeftPointer();
		// 子供のextent計算
		if ( leftpointer instanceof Node ) {
			((Node)leftpointer).accept(this);	
			// acceptから帰ってきた時点で、インスタンス変数extentsに、子供のextentが登録されている。
			child_extent.unionHorizontal(extents.get(leftpointer));
		}
		for ( int i=0; i < node.getMaxKeys(); i++ ) {
			Object pointer = node.getPointer(i);
			if ( pointer instanceof Node ) {
				((AbstractNode)pointer).accept(this);
				// acceptから帰ってきた時点で、インスタンス変数extentsに、子供のextentが登録されている。
				child_extent.unionHorizontal(extents.get(pointer));
			}
		}
		// 自分のextentの計算
		NodeExtent node_extent = getExtent(node);
		// 子供とのextentの結合
		if ( !node.isLeaf() ) {
			// 子供のextentと、縦のマージン分をextentとしてくっつける
			child_extent.unionVertical(new NodeExtent(1,gc.getNodeHorizontalMirgin()) );
			// 子供のextentとくっつける
			child_extent.unionVertical(node_extent);
			node_extent = child_extent;
		}
		
		extents.put(node, node_extent);
	}
	
	private NodeExtent getExtent( Node n ) {
		Dimension d = gc.getBounds(n);
		d.setSize(d.getWidth()+gc.getNodeHorizontalMirgin(), d.getHeight());	// 横のマージン分広げておく
		return new NodeExtent(d);
	}
}
